package br.com.petsis.funcionalidades.despesas;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage.Severity;

import br.com.petsis.entity.Despesa;
import br.com.petsis.entity.MesDespesa;

@Name("despesasController")
@Scope(ScopeType.CONVERSATION)
//@Restrict(value="#{identity.hasRole('Administrador')}")
public class DespesasController {
	
	@In(create=true)
	private EntityManager entityManager;
	
	private List<Despesa> despesas;
	
	private MesDespesa mesReferencia;
	
	private Despesa despesaEdicao;
	
	private Float valorTotalDespesas;
	
	private Float valorTotalPedidos;

	private Float valorTotalPedidosNaoPagos;
	
	private Float valorTotalPacotes;
	
	private Float valorTotalVales;
	
	private Float valorTotalLiquido;
	
	private boolean exibirPopupNovaDespesa;
	
	private List<SelectItem> listaTiposDespesa;
	
	private boolean isEdicao;
	
	public void onLoad(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		Integer mes = calendar.get(Calendar.MONTH);
		Integer ano = calendar.get(Calendar.YEAR);
		mesReferencia = recuperaMesDespesa(mes, ano);
		
		mesReferencia = entityManager.merge(mesReferencia);

		entityManager.flush();
		
		if(mesReferencia.getFlgStatus().equals(MesDespesa.STATUS_MES_DESPESA_FECHADO)){
			calcularFechamentoMes();
		}
	}
	
	public void inicializaPopupNovaDespesa(){
		setDespesaEdicao(new Despesa());
		setExibirPopupNovaDespesa(true);
		isEdicao = false;
	}
	
	public void editarDespesa(Despesa despesa){
		setDespesaEdicao(despesa);
		setExibirPopupNovaDespesa(true);
		isEdicao = true;
	}
	
	public void cancelarNovaDespesa(){
		setExibirPopupNovaDespesa(false);
	}
	
	public void salvarNovaDespesa(){
		getDespesaEdicao().setFlgAtivo('T');
		if(!isEdicao){
			getDespesas().add(getDespesaEdicao());
			getDespesaEdicao().setVlrDespesa(0F);
		}
		setExibirPopupNovaDespesa(false);
	}
	
	public void excluir(Despesa despesa){
		despesa.setFlgAtivo('F');
		entityManager.merge(despesa);
		entityManager.flush();
		getDespesas().remove(despesa);
	}
	
	public String salvar(){
		mesReferencia = entityManager.merge(getMesReferencia());
		
		
		for(Despesa d : getDespesas()){
			d.setMesDespesa(mesReferencia);
			if(d.getVlrDespesa() == null){
				d.setVlrDespesa(0F);
			}
			entityManager.merge(d);
		}
		entityManager.flush();
		calculaTotalDespesas();
		getMesReferencia().setVlrTotalDespesas(getValorTotalDespesas());
		FacesMessages.instance().add(Severity.INFO,"Despesas salvas com sucesso");
		return "persisted";
	}
	
	public void calcularFechamentoMes(){
		Double totalPedidos = (Double)entityManager.createQuery("select SUM(p.vlrPedido) from Pedido p where MONTH(p.dtaPedido) = :mes and YEAR(p.dtaPedido) = :ano and p.flgPago = 'T'")
			.setParameter("mes", getMesReferencia().getMesRef()+1)
			.setParameter("ano", getMesReferencia().getAnoRef())
			.getSingleResult();
		Double totalPedidosNaoPagos = (Double)entityManager.createQuery("select SUM(p.vlrPedido) from Pedido p where MONTH(p.dtaPedido) = :mes and YEAR(p.dtaPedido) = :ano and p.flgPago = 'F'")
			.setParameter("mes", getMesReferencia().getMesRef()+1)
			.setParameter("ano", getMesReferencia().getAnoRef())
			.getSingleResult();
		Double totalPacotes = (Double)entityManager.createQuery("select SUM(p.vlrPacote) from Pacote p where MONTH(p.dtaPagamento) = :mes and YEAR(p.dtaPagamento) = :ano")
			.setParameter("mes", getMesReferencia().getMesRef()+1)
			.setParameter("ano", getMesReferencia().getAnoRef())
			.getSingleResult();
		Double totalVales = (Double)entityManager.createQuery("select SUM(v.vlrVale) from Vale v where MONTH(v.dtaVale) = :mes and YEAR(v.dtaVale) = :ano")
			.setParameter("mes", getMesReferencia().getMesRef()+1)
			.setParameter("ano", getMesReferencia().getAnoRef())
			.getSingleResult();
		
		despesas = entityManager
			.createQuery("select d from Despesa d where d.mesDespesa.idMesDespesa = :idMesDespesa and d.flgAtivo = 'T'")
			.setParameter("idMesDespesa",getMesReferencia().getIdMesDespesa())
			.getResultList();
		
		calculaTotalDespesas();
		totalPedidos = totalPedidos != null ? totalPedidos : 0F;
		totalPedidosNaoPagos = totalPedidosNaoPagos != null ? totalPedidosNaoPagos : 0F;
		totalPacotes = totalPacotes != null ? totalPacotes : 0F;
		totalVales = totalVales != null ? totalVales : 0F;
		Double totalLiquido = (totalPedidos + totalPacotes) - (totalVales + getValorTotalDespesas());
		setValorTotalPedidos(totalPedidos.floatValue());
		setValorTotalPedidosNaoPagos(totalPedidosNaoPagos.floatValue());
		setValorTotalPacotes(totalPacotes.floatValue());
		setValorTotalVales(totalVales.floatValue());
		setValorTotalLiquido(totalLiquido.floatValue());
	}
	
	public void calculaTotalDespesas(){
		float valor = 0F;
		/*despesas = entityManager
			.createQuery("select d from Despesa d where d.mesDespesa.idMesDespesa = :idMesDespesa and d.flgAtivo = 'T'")
			.setParameter("idMesDespesa",getMesReferencia().getIdMesDespesa())
			.getResultList();*/
		for(Despesa d : getDespesas()){
			if(d.getVlrDespesa() == null){
				d.setVlrDespesa(0F);
			}
			valor += d.getVlrDespesa();
		}
		setValorTotalDespesas(valor);
	}
	
	public boolean validaCamposObrigatorios(){
		for(Despesa d : getDespesas()){
			if(d.getDtaPagamento() == null){
				return false;
			}
			if(d.getVlrDespesa() == null ||
					d.getVlrDespesa().equals(0F)){
				return false;
			}
		}
		return true;
	}
	
	public String verificaCorBackground(Integer indexOf){
		if(indexOf % 2 == 0){
			return "white";
		}else{
			return "#F0FFFF";
		}
	}
	
	public void fecharMes(){
		if(!validaCamposObrigatorios()){
			FacesMessages.instance().add(Severity.ERROR,"Você possui despesas em aberto ou com valor igual a 0. Verifique-as antes de fechar o m�s.");
			return;
		}
		if(getMesReferencia().getFlgStatus().equals(MesDespesa.STATUS_MES_DESPESA_ABERTO)){
			getMesReferencia().setFlgStatus(MesDespesa.STATUS_MES_DESPESA_FECHADO);
			entityManager.merge(getMesReferencia());
			MesDespesa mesSeguinte = null;
			MesDespesa mesSalvo = null;
			for(Despesa d : getDespesas()){
				if(Despesa.TIPO_DESPESA_MENSAL.equals(d.getTpoDespesa())){
					if(mesSeguinte == null){
						mesSeguinte = new MesDespesa();
						if(getMesReferencia().getMesRef().equals(11)){
							mesSeguinte.setMesRef(0);
							mesSeguinte.setAnoRef(getMesReferencia().getAnoRef() + 1);
						}else{
							Integer proxMes = getMesReferencia().getMesRef() + 1;
							mesSeguinte.setMesRef(proxMes);
							mesSeguinte.setAnoRef(getMesReferencia().getAnoRef());
						}
						mesSeguinte.setFlgStatus(MesDespesa.STATUS_MES_DESPESA_ABERTO);
						mesSalvo = entityManager.merge(mesSeguinte);
					}
					Despesa novaDespesa = new Despesa(d);
					Calendar calendarVencimento = Calendar.getInstance();
					calendarVencimento.setTime(d.getDtaVencimento());
					if(calendarVencimento.get(Calendar.MONTH) == 11){
						calendarVencimento.set(Calendar.MONTH, 0);
						calendarVencimento.set(Calendar.YEAR, calendarVencimento.get(Calendar.YEAR)+1);
					}else{
						calendarVencimento.set(Calendar.MONTH, calendarVencimento.get(Calendar.MONTH)+1);
					}
					novaDespesa.setDtaVencimento(calendarVencimento.getTime());
					novaDespesa.setMesDespesa(mesSalvo);
					entityManager.merge(novaDespesa);
				}
				if(Despesa.TIPO_DESPESA_ANUAL.equals(d.getTpoDespesa())){
					if(mesSeguinte == null){
						mesSeguinte = new MesDespesa();
						mesSeguinte.setMesRef(getMesReferencia().getMesRef());
						Integer proxAno = getMesReferencia().getAnoRef() + 1;
						mesSeguinte.setAnoRef(proxAno);
						mesSeguinte.setFlgStatus(MesDespesa.STATUS_MES_DESPESA_ABERTO);
						mesSalvo = entityManager.merge(mesSeguinte);
					}
					Despesa novaDespesa = new Despesa(d);
					Calendar calendarVencimento = Calendar.getInstance();
					calendarVencimento.setTime(d.getDtaVencimento());
					calendarVencimento.set(Calendar.YEAR, calendarVencimento.get(Calendar.YEAR)+1);
					novaDespesa.setDtaVencimento(calendarVencimento.getTime());
					novaDespesa.setMesDespesa(mesSalvo);
					Despesa despesaSalva = entityManager.merge(novaDespesa);
				}
			}
		}else{
			getMesReferencia().setFlgStatus(MesDespesa.STATUS_MES_DESPESA_FECHADO);
			entityManager.merge(getMesReferencia());
		}
		entityManager.flush();
		calcularFechamentoMes();
	}
	
	public void reabrirMes(){
		getMesReferencia().setFlgStatus(MesDespesa.STATUS_MES_DESPESA_REABERTO);
		entityManager.merge(getMesReferencia());
		entityManager.flush();
	}
	
	public void avancarMes(){
		Integer mes = getMesReferencia().getMesRef();
		Integer ano = getMesReferencia().getAnoRef();
		if(mes.equals(11)){
			setMesReferencia(recuperaMesDespesa(0, ++ano));
		}else{
			setMesReferencia(recuperaMesDespesa(++mes, ano));
		}
		setDespesas(null);
		getDespesas();
		calcularFechamentoMes();
	}
	
	public void voltarMes(){
		Integer mes = getMesReferencia().getMesRef();
		Integer ano = getMesReferencia().getAnoRef();
		if(mes.equals(0)){
			setMesReferencia(recuperaMesDespesa(11, --ano));
		}else{
			setMesReferencia(recuperaMesDespesa(--mes, ano));
		}
		if(getMesReferencia().getIdMesDespesa() == null){
			getMesReferencia().setFlgStatus(MesDespesa.STATUS_MES_DESPESA_FECHADO);
		}
		calcularFechamentoMes();
		setDespesas(null);
		getDespesas();
	}
	
	public String recuperaIconeStatus(Despesa despesa){
		SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy");
		if(despesa.getDtaPagamento() != null){
			return "img/icone_verde.png";
		}else
		if(formato.format(despesa.getDtaVencimento()).equals(formato.format(new Date()))){
			return "img/icone_amarelo.png";
		}else
		if(despesa.getDtaVencimento().before(new Date())){
			return "img/icone_vermelho.png";
		}else{
			return "img/icone_verde.png";
		}
	}
	
	public MesDespesa recuperaMesDespesa(Integer mes, Integer ano){
		try{
			return (MesDespesa)entityManager
				.createQuery("select m from MesDespesa m where m.mesRef = :mes and m.anoRef = :ano")
				.setParameter("mes", mes)
				.setParameter("ano", ano)
				.getSingleResult();
		}catch(NoResultException e){
			MesDespesa mesDespesa = new MesDespesa();
			mesDespesa.setMesRef(mes);
			mesDespesa.setAnoRef(ano);
			mesDespesa.setFlgStatus(MesDespesa.STATUS_MES_DESPESA_ABERTO);
			return mesDespesa;
		}
	}
	
	public String recuperaMesExtenso(Integer mesInt){
		SimpleDateFormat format = new SimpleDateFormat("MMMM");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.MONTH, mesInt);
		return format.format(calendar.getTime());
		
	}

	public Float getValorTotalDespesas() {
		if (valorTotalDespesas == null) {
			valorTotalDespesas = 0F;
		}
		return valorTotalDespesas;
	}

	public void setValorTotalDespesas(Float valorTotalDespesas) {
		this.valorTotalDespesas = valorTotalDespesas;
	}

	public Float getValorTotalPedidos() {
		if (valorTotalPedidos == null) {
			valorTotalPedidos = 0F;
		}
		return valorTotalPedidos;
	}

	public void setValorTotalPedidos(Float valorTotalPedidos) {
		this.valorTotalPedidos = valorTotalPedidos;
	}

	public Float getValorTotalPedidosNaoPagos() {
		if (valorTotalPedidosNaoPagos == null) {
			valorTotalPedidosNaoPagos = 0F;
		}
		return valorTotalPedidosNaoPagos;
	}

	public void setValorTotalPedidosNaoPagos(Float valorTotalPedidosNaoPagos) {
		this.valorTotalPedidosNaoPagos = valorTotalPedidosNaoPagos;
	}

	public Float getValorTotalPacotes() {
		if (valorTotalPacotes == null) {
			valorTotalPacotes = 0F;
		}
		return valorTotalPacotes;
	}

	public void setValorTotalPacotes(Float valorTotalPacotes) {
		this.valorTotalPacotes = valorTotalPacotes;
	}

	public Float getValorTotalVales() {
		if (valorTotalVales == null) {
			valorTotalVales = 0F;
		}
		return valorTotalVales;
	}

	public void setValorTotalVales(Float valorTotalVales) {
		this.valorTotalVales = valorTotalVales;
	}

	public Float getValorTotalLiquido() {
		if (valorTotalLiquido == null) {
			valorTotalLiquido = 0F;
		}
		return valorTotalLiquido;
	}

	public void setValorTotalLiquido(Float valorTotalLiquido) {
		this.valorTotalLiquido = valorTotalLiquido;
	}

	public boolean isExibirPopupNovaDespesa() {
		return exibirPopupNovaDespesa;
	}

	public void setExibirPopupNovaDespesa(boolean exibirPopupNovaDespesa) {
		this.exibirPopupNovaDespesa = exibirPopupNovaDespesa;
	}

	public List<SelectItem> getListaTiposDespesa() {
		if (listaTiposDespesa == null) {
			listaTiposDespesa = new ArrayList<SelectItem>();
			listaTiposDespesa.add(new SelectItem(null,"Selecione"));
			listaTiposDespesa.add(new SelectItem(Despesa.TIPO_DESPESA_UNICA,"Única"));
			listaTiposDespesa.add(new SelectItem(Despesa.TIPO_DESPESA_MENSAL,"Mensal"));
			listaTiposDespesa.add(new SelectItem(Despesa.TIPO_DESPESA_ANUAL,"Anual"));
		}
		return listaTiposDespesa;
	}

	public void setListaTiposDespesa(List<SelectItem> listaTiposDespesa) {
		this.listaTiposDespesa = listaTiposDespesa;
	}

	public List<Despesa> getDespesas() {
		if (despesas == null) {
			despesas = entityManager
				.createQuery("select d from Despesa d where d.mesDespesa.idMesDespesa = :idMesDespesa and d.flgAtivo = 'T'")
				.setParameter("idMesDespesa",getMesReferencia().getIdMesDespesa())
				.getResultList();
			calculaTotalDespesas();
		}
		return despesas;
	}

	public void setDespesas(List<Despesa> despesas) {
		this.despesas = despesas;
	}

	public MesDespesa getMesReferencia() {
		if (mesReferencia == null) {
			onLoad();
		}
		return mesReferencia;
	}

	public void setMesReferencia(MesDespesa mesReferencia) {
		this.mesReferencia = mesReferencia;
	}

	public Despesa getDespesaEdicao() {
		if (despesaEdicao == null) {
			despesaEdicao = new Despesa();
		}
		return despesaEdicao;
	}

	public void setDespesaEdicao(Despesa despesaEdicao) {
		this.despesaEdicao = despesaEdicao;
	}

	public Integer recuperaQtdeDespesasVencendoHoje(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		Integer mes = calendar.get(Calendar.MONTH);
		Integer ano = calendar.get(Calendar.YEAR);
		MesDespesa mesDespesa = recuperaMesDespesa(mes, ano);
		int cont = 0;
		if(mesDespesa.getIdMesDespesa() != null){
			List<Despesa> listaDespesas = entityManager
				.createQuery("select d from Despesa d where d.mesDespesa.idMesDespesa = :idMesDespesa and d.flgAtivo = 'T'")
				.setParameter("idMesDespesa",mesDespesa.getIdMesDespesa())
				.getResultList();
			SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy");
			for(Despesa d : listaDespesas){
				if(formato.format(d.getDtaVencimento()).equals(formato.format(new Date())) &&
						d.getDtaPagamento() == null){
					cont++;
				}
			}
		}
		return cont;
	}
}
